package net.aiion.weave.impl.resources;

import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;

import net.aiion.weave.impl.resources.provider.ResourceProviderFactoryImpl;
import net.aiion.weave.impl.resources.url.ClassLoaderURLProvider;
import net.aiion.weave.impl.resources.url.SystemClasspathURLProvider;
import net.aiion.weave.spi.resources.Resource;
import net.aiion.weave.spi.resources.ResourceFinder;
import net.aiion.weave.spi.resources.ResourceListener;
import net.aiion.weave.spi.resources.provider.ResourceProviderFactory;
import net.aiion.weave.spi.resources.url.URLProvider;

public class ResourceFinderImpl implements ResourceFinder
{
    private final Collection<ResourceListener> resourceListeners;

    private ResourceProviderFactory resourceProviderFactory;

    private Collection<Resource> resourcesFound;

    public ResourceFinderImpl() {
        resourceListeners = new ArrayList<>();
        resourceProviderFactory = new ResourceProviderFactoryImpl();
    }

    @Override
    public void setResourceProviderFactory(final ResourceProviderFactory aResourceProviderFactory) {
        resourceProviderFactory = aResourceProviderFactory;
    }

    @Override
    public ResourceProviderFactory getResourceProviderFactory() {
        return resourceProviderFactory;
    }

    @Override
    public void addResourceListener(final ResourceListener aResourceListener) {
        resourceListeners.add(aResourceListener);
    }

    @Override
    public void removeResourceListener(final ResourceListener aResourceListener) {
        resourceListeners.remove(aResourceListener);
    }

    @Override
    public void findResources() {
        startResourceListeners();
        resourcesFound = new ArrayList<>();
        // TODO Detect JBoss AS 7.1 and add set JBossAS71URLConverter to the URLProviders
        // There is currently no support for JBoss AS registered.
        findResources1(new ClassLoaderURLProvider());
        findResources1(new SystemClasspathURLProvider());
        resourcesFound = null;
        stopResourceListeners();
    }

    @Override
    public void findResources(final URLProvider aURLProvider) {
        startResourceListeners();
        resourcesFound = new ArrayList<>();
        findResources1(aURLProvider);
        resourcesFound = null;
        stopResourceListeners();
    }

    private void findResources1(final URLProvider aURLProvider) {
        for (URL url : aURLProvider) {
            for (Resource resource : resourceProviderFactory.createResourceProvider(url)) {
                notifyResourceListeners(resource);
            }
        }
    }

    private void startResourceListeners() {
        for (ResourceListener resourceListener : resourceListeners) {
            resourceListener.onStartup();
        }
    }

    private void notifyResourceListeners(final Resource aResource) {
        if (resourcesFound.contains(aResource)) {
            return;
        }

        resourcesFound.add(aResource);

        for (ResourceListener resourceListener : resourceListeners) {
            resourceListener.resourceFound(aResource);
        }
    }

    private void stopResourceListeners() {
        for (ResourceListener resourceListener : resourceListeners) {
            resourceListener.onShutdown();
        }
    }
}
